import cgi
import os
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import urllib2
import requests
import simplejson
import json
import jsontemplate
import config
import modify
import sys

url = 'http://us.api.invisiblehand.co.uk/v1/products'

modify.read_input('indext.txt')
modify.read_input('index2t.txt')

modify.read_to_template1(config.ts_1)
modify.read_to_template2(config.ts_2)

# function to render template for state where data and budget are present
def rendert2():
  resultString=config.t2.expand(config.data)
  color = modify.budgetWarningLevel(config.budget, config.selectedItems, config.data)
  resultString = resultString.replace('!color!', str(color))
  resultString = resultString.replace('!budget!', str(config.budget))
  recDic = modify.recommend(config.budget, config.selectedItems, config.data)
  for key,value in recDic.items():
    if key not in config.selectedItems:
	    recDic[key] = "Recommended Price: $" + str(recDic[key])
  for key,value in recDic.items():
    tempString='!' + key + '!'
    resultString=resultString.replace(tempString,value)
  resultString = resultString.replace('!totalPrice!', str(config.totalPrice))
  resultString = resultString.replace('!search!', '')
  return resultString

# function to render template where only data is present(no budget)
def rendert():
  resultString = config.t1.expand(config.data)
  resultString = resultString.replace('!budget!', '')
  resultString = resultString.replace('!totalPrice!', str(config.totalPrice))
  resultString = resultString.replace('!search!', '')
  selecDic = modify.selections(config.selectedItems, config.data)
  for key,value in selecDic.items():
	  tempString = '!' + key + '!'
	  resultString=resultString.replace(tempString,value)
  return resultString
  
# function to render more info
def renderInfo(searchterm,itmId, itmPrice):
  for x in config.data:
    if x['searchterm']==searchterm:
      for y in x['results']:
        if y['id'] == itmId:
          category=""
          i = 0
          for z in y['categories']:
            if i > 0:
              category = category + ", " + (str(z)).replace('\'','')
            else:
              category = "Categories:" + (str(z)).replace('\'','')
              i = 1		
          if config.budget == '':
            bdgt = 'No Budget Available'
          else:
            bdgt = 'Budget: $ %.2f' % config.budget
    
          if 'best_page' in y:
            if y['best_page']['in_stock'] is True:
              stock = "Currently In Stock"
            else:
              stock ="Out of Stock"
            template_values = {'searchterm' : searchterm, 'id':itmId, 'budget': bdgt, 'title': y['title'], 'price': itmPrice, 'image': y['best_page']['image_url'], 'retailer':y['best_page']['retailer_name'], 'description': y['best_page']['description'], 'stock': stock, 'brand':y['brands'], 'url':y['best_page']['original_url'], 'category':category, 'outPrice': str( '$ %.2f' % float(itmPrice))}
          else:
            stock = "Out of Stock"
            template_values = {'searchterm' : searchterm, 'id':itmId, 'budget': bdgt, 'title': y['title'], 'price': itmPrice, 'image': '', 'retailer':'', 'description': 'No Description Available', 'stock': stock, 'brand':y['brands'], 'url':'', 'category':category, 'outPrice': 'No Price Available'}

          path = os.path.join(os.path.dirname(__file__),'info.html')
          return template.render(path,template_values)
  return 'Product not Found'
 

# function which chooses which data template to render
def rendData():
  if (config.budget == ''):
    resultString = rendert()
  else:
    resultString = rendert2()
  return resultString
  
# select function
# used for consistently maintained button functionality across different displays(states)
def select(searchterm, selectedItm, but):
  selectedItm = selectedItm.split('-')
  
  itmId = selectedItm[0]
  
  if len(selectedItm)<2:
    itmPrice =0.00
  else:
    itmPrice = selectedItm[1]

  if but =='Select':
    
    print "\n\n" + searchterm + "\n\n";
    #add the selected product to selectedItems dictionary
    if modify.search_items(searchterm):
      modify.add_id(itmId, searchterm)
      modify.add_price(itmPrice, searchterm)
      modify.add_total(itmPrice)                      
    else:
      #remove old item
      lastPrice = modify.get_price(searchterm)
      modify.sub_total(lastPrice)
      #add new item
      modify.add_id(itmId, searchterm)
      modify.add_price(itmPrice, searchterm)
      modify.add_total(itmPrice)
			
	#get rendered resulting output
    resultString = rendData()	
  elif but =='Reset':
	  if modify.search_items(searchterm) is False:
	    lastPrice = modify.get_price(searchterm)
	    modify.sub_total(lastPrice)
	    modify.removeSelect(searchterm)
	  resultString = rendData()
  elif but == 'More Info':
	    resultString = renderInfo(searchterm, itmId, itmPrice)
  elif but == 'Return to Results':
    resultString = rendData()
  else:
    print "Error: Search selection did not match any option in function select(but)"
    print "Selected button value is " + str(but)
    resultString = "Error: Button did not match any valid values"
  return resultString

	
	
	
# main page appears on load
class MainPage(webapp.RequestHandler):
  def get(self):
	# render the initial page
    template_values={'budget': config.budget}
    path = os.path.join(os.path.dirname(__file__),'index.html')
    self.response.out.write(template.render(path,template_values))
    
# Display function for budget value submit
# Alternates with BudgetReload
# Reads in budget and switches view to index2.html if no data and index2t.txt if data
class BudgetSubmit(webapp.RequestHandler):
  def post(self):
	# read in budget
    formBudget=self.request.get('budget')
    modify.update_budget(formBudget)
	
	# clean initial budget(checks validity and removes strings)
    intBudget = config.budget
    if (config.budget != ''):
      if intBudget[0] == '$':
        config.budget = config.budget[1:]
        if config.budget.isnumeric():
          config.budget = float(config.budget)
        else:
          modify.update_budget('')
      elif config.budget[0] != '$':
        if config.budget.isnumeric():
          config.budget = float(config.budget)
        else:
          modify.update_budget('')

    # render the page(choose page based off of presence of budget and data)
    if(len(config.data) == 0):
      template_values={'budget': config.budget}
      if (config.budget == ''):
        path = os.path.join(os.path.dirname(__file__),'index.html')
      else:
        path = os.path.join(os.path.dirname(__file__),'index2.html')
      resultString = template.render(path,template_values)
    else:
      resultString = rendData()
	
	# render the page(display output)
    self.response.out.write(resultString)

	
# Display function for budget reset(budget value previously stored, reset value)
# Alternates with BudgetSubmit
# Deletes previous budget and switches view to index.html if no data and indext.txt if data
class BudgetReload(webapp.RequestHandler):
  def post(self):
    modify.update_budget('')

	# rendering: choose between two possible state resulting from a budget reset action
    if(len(config.data) == 0):
      template_values={'budget': config.budget}
      path = os.path.join(os.path.dirname(__file__),'index.html')
      resultString = template.render(path,template_values)
    else:
      resultString = rendert()
	
	#render the page(display output)
    self.response.out.write(resultString)
 
	 
# Return Action
# used by Info.html page to return to the main results display
# has buttons: "Select" and "Return to Results"	
class Return(webapp.RequestHandler):
  def post(self):
	  form = cgi.FieldStorage()
	  searchterm = self.request.get('search')
	  print "\n\n\n", searchterm,"\n";
	  selectedItm = self.request.get(searchterm)	
	  # perform actions consistent with possible result buttons and return resulting display
	  resultString = select(searchterm, selectedItm, str(self.request.get('entry')))
		
	  # render the page(display output)
	  self.response.out.write(resultString)
 
	 
# Function when values are selected
# Reads in data on what selected item is updates total price and recommended prices
# Display is either indext.txt if no budget or index2t.txt if budget     
class ItemSelect(webapp.RequestHandler):
  def post(self):
    form = cgi.FieldStorage()
    searchterm = self.request.get('search')	
	# checks if empty selection
    if len(self.request.get(searchterm)) != 0:
	  # run valid select
      selectedItm = self.request.get(searchterm)
      resultString = select(searchterm, selectedItm, str(self.request.get('Bsubmit')))
    else:
	  # checks if Reset with no dropdown selection
      if str(self.request.get('Bsubmit'))=='Reset':
        if modify.search_items(searchterm) is False:
          lastPrice = modify.get_price(searchterm)
          modify.sub_total(lastPrice)
          modify.removeSelect(searchterm)
        resultString = rendData()
		# checks if More Info with no selection(previous and in drop down)
      elif self.request.get('Bsubmit')=='More Info':
        if searchterm in config.selectedItems:
          resultString = renderInfo(searchterm, config.selectedItems[searchterm]['id'], config.selectedItems[searchterm]['price'])
        else:
  	      resultString = rendData()
		  # checks for select with no selection
      else: 
  	    resultString = rendData()		
	  # render the page(display output)
    self.response.out.write(resultString)
     
      
# Search function(newSearch and addItem)
# Reads in searchterms and type of search, performs search, switches view to either indext.txt if no budget and index2t.txt if budget
class SearchController(webapp.RequestHandler):
  def get(self):
    form = cgi.FieldStorage()
    formSearch=form.getvalue('search')
    modify.update_search(formSearch)
    # calculate something

    if str(config.search) != "None":
     searchterm = {'app_key':config.app_key,'app_id':config.app_id,'order':"asc",'query':config.search }
     r=requests.get(url,params=searchterm)
      
     tempdict = r.json()
     tempdict['searchterm'] = config.search

     if self.request.get('search_type')=='newSrch': 
      modify.reset_total()     
      for x in range (0,len(config.data)):
       modify.clear_data()
      modify.add_data(tempdict)
     elif self.request.get('search_type')=='addItm':
       modify.add_data(tempdict)

    elif (self.request.get('search_type')=='newSrch') & (str(config.search) == 'None'): 
      modify.reset_total() 
      modify.update_budget('')    
      for x in range (0,len(config.data)):
       modify.clear_data()

    

    # set up the template_values with the data to insert into html
    template_values= {'budget': config.budget}
    if ((len(config.data) == 0) & (config.budget == '')):
      path = os.path.join(os.path.dirname(__file__),'index.html')
      self.response.out.write(template.render(path,template_values))
    elif ((len(config.data) == 0) & (config.budget != '')):
      path = os.path.join(os.path.dirname(__file__),'index2.html')
      self.response.out.write(template.render(path,template_values))
    else:
      resultString = rendData()
      self.response.out.write(resultString)
      

    


# create this global variable that represents the application and specifies which class
# should handle each page in the site
app = webapp.WSGIApplication(
                                        # MainPage handles the home page load
                                     [('/', MainPage),
                                      ('/onSearch', SearchController), 
                                      ('/onSubmit', BudgetSubmit),
                                      ('/onReset', BudgetReload),
                                      ('/onSelect', ItemSelect),
                                      ('/onReturn', Return)],
                                     debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()